home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / ipcmd.c < prev    next >
Text File  |  1993-07-30  |  13KB  |  572 lines

  1. /* IP-related user commands
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  /* Mods by PA0GRI */
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include "global.h"
  8. #include "config.h"
  9. #include "mbuf.h"
  10. #include "internet.h"
  11. #include "timer.h"
  12. #include "netuser.h"
  13. #include "iface.h"
  14. #include "session.h"
  15. #include "ip.h"
  16. #include "cmdparse.h"
  17. #include "commands.h"
  18. #include "rip.h"
  19. #include "rspf.h"
  20.  
  21. int32 Ip_addr;
  22.  
  23. static int doadd __ARGS((int argc,char *argv[],void *p));
  24. #ifdef    IPACCESS
  25. static int doaccess __ARGS((int argc,char *argv[],void *p));
  26. #endif
  27. static int dodrop __ARGS((int argc,char *argv[],void *p));
  28. static int doflush __ARGS((int argc,char *argv[],void *p));
  29. static int doipaddr __ARGS((int argc,char *argv[],void *p));
  30. static int doipstat __ARGS((int argc,char *argv[],void *p));
  31. static int dolook __ARGS((int argc,char *argv[],void *p));
  32. static int dortimer __ARGS((int argc,char *argv[],void *p));
  33. static int dottl __ARGS((int argc,char *argv[],void *p));
  34. static int dumproute __ARGS((struct route *rp));
  35.  
  36. static struct cmds Ipcmds[] = {
  37. #ifdef    IPACCESS
  38.     "access",    doaccess,    0,    0, NULLCHAR,
  39. #endif
  40.     "address",    doipaddr,    0,    0, NULLCHAR,
  41.     "rtimer",    dortimer,    0,    0, NULLCHAR,
  42.     "status",    doipstat,    0,    0, NULLCHAR,
  43.     "ttl",        dottl,        0,    0, NULLCHAR,
  44.     NULLCHAR,
  45. };
  46. /* "route" subcommands */
  47. static struct cmds Rtcmds[] = {
  48.     "add",        doadd,        0,    3,
  49.     "route add <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]",
  50.  
  51.     "addprivate",    doadd,        0,    3,
  52.     "route addprivate <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]",
  53.  
  54.     "drop",        dodrop,        0,    2,
  55.     "route drop <dest addr>[/<bits>]",
  56.  
  57.     "flush",    doflush,    0,    0,
  58.     NULLCHAR,
  59.  
  60.     "lookup",    dolook,        0,    2,
  61.     "route lookup <dest addr>",
  62.  
  63.     NULLCHAR,
  64. };
  65.  
  66. int
  67. doip(argc,argv,p)
  68. int argc;
  69. char *argv[];
  70. void *p;
  71. {
  72.     return subcmd(Ipcmds,argc,argv,p);
  73. }
  74. #ifdef    IPACCESS
  75. static int
  76. doaccess(argc,argv,p)
  77. int argc;
  78. char *argv[];
  79. void *p;
  80. {
  81.     struct iface *ifp;
  82.     int32 source,target;
  83.     unsigned sbits,tbits;
  84.     char *bitp;
  85.     int16 lport,hport,protocol,state;
  86.     char *cp; /* for printing the table */
  87.     struct rtaccess *tpacc;
  88.     struct rtaccess *btacc;
  89.     struct rtaccess *bfacc;
  90.     struct rtaccess *head;
  91.     char tmpbuf[15];
  92.  
  93.     if(argc == 1){ /* print out the table */
  94.         tprintf("Source Address  Len Dest Address    Len Interface    Proto Low   High  State\n");
  95.         for(tpacc = IPaccess;tpacc != NULLACCESS;tpacc = tpacc->nxtiface){
  96.             for(btacc = tpacc;btacc != NULLACCESS;btacc = btacc->nxtbits){
  97.                 if(btacc->source != 0)
  98.                     cp = inet_ntoa(btacc->source);
  99.                 else
  100.                     cp = "all";
  101.                 tprintf("%-16s",cp);
  102.                 tprintf("%2u  ",btacc->sbits);
  103.                 if(btacc->target != 0)
  104.                     cp = inet_ntoa(btacc->target);
  105.                 else
  106.                     cp = "all";
  107.                 tprintf("%-16s",cp);
  108.                 tprintf("%2u  ",btacc->tbits);
  109.                 tprintf("%-13s",btacc->iface->name);
  110.                 switch (btacc->protocol) {
  111.                     case 0:
  112.                         cp = "any";
  113.                         break;
  114.                     case ICMP_PTCL:
  115.                         cp = "icmp";
  116.                         break;
  117.                     case TCP_PTCL:
  118.                         cp = "tcp";
  119.                         break;
  120.                     case UDP_PTCL:
  121.                         cp = "udp";
  122.                         break;
  123.                     default:
  124.                         sprintf(tmpbuf, "%d",btacc->protocol);
  125.                         cp = tmpbuf;
  126. /*                        cp = itoa(btacc->protocol,tmpbuf,10); non ansi */
  127.                 }
  128.                 tprintf("%-5s ",cp);
  129.                 tprintf("%5u ",btacc->lowport);
  130.                 tprintf("%5u ",btacc->highport);
  131.                 if(btacc->status)
  132.                     cp = "deny";
  133.                 else
  134.                     cp = "permit";
  135.                 tprintf("%-6s\n",cp);
  136.             }
  137.         }
  138.         return 0;
  139.     }
  140.  
  141.     if(strcmp(argv[1],"permit") == 0){
  142.         state = 0;
  143.     } else {
  144.         if((strcmp(argv[1],"deny") == 0) 
  145.         || (strcmp(argv[1],"delete") == 0)){
  146.             state = -1;
  147.         } else {
  148.             tprintf(" Format: ip access <permit|deny|delete> <proto> <src addr>[/<bits>] <dest addr>[/<bits>] <if name> [low [high]]\n");
  149.             return 1;
  150.         }
  151.     }
  152.  
  153.     switch (*argv[2]){
  154.         case 'a':    /* ANY */
  155.             protocol = 0;
  156.             break;
  157.         case 'i':    /* ICMP */
  158.             protocol = ICMP_PTCL;
  159.             break;
  160.         case 't':    /* TCP */
  161.             protocol = TCP_PTCL;
  162.             break;
  163.         case 'u':    /* UDP */
  164.             protocol = UDP_PTCL;
  165.             break;
  166.         default:
  167.             protocol = atoi(argv[2]);
  168.     }
  169.  
  170.     if(strcmp(argv[3],"all") == 0){
  171.         source = 0;
  172.         sbits = 0;
  173.     } else {
  174.         /* If IP address is followed by an optional slash and
  175.          * a length field, (e.g., 128.96/16) get it;
  176.          * otherwise assume a full 32-bit address
  177.          */
  178.         if((bitp = strchr(argv[3],'/')) != NULLCHAR){
  179.             /* Terminate address token for resolve() call */
  180.             *bitp++ = '\0';
  181.             sbits = atoi(bitp);
  182.         } else
  183.             sbits = 32;
  184.  
  185.         if((source = resolve(argv[3])) == 0){
  186.             tprintf(Badhost,argv[3]);
  187.             return 1;
  188.         }
  189.     }
  190.     if(strcmp(argv[4],"all") == 0){
  191.         target = 0;
  192.         tbits = 0;
  193.     } else {
  194.         if((bitp = strchr(argv[4],'/')) != NULLCHAR){
  195.             *bitp++ = '\0';
  196.             tbits = atoi(bitp);
  197.         } else
  198.             tbits = 32;
  199.  
  200.         if((target = resolve(argv[4])) == 0){
  201.             tprintf(Badhost,argv[4]);
  202.             return 1;
  203.         }
  204.     }
  205.     
  206.     if((ifp = if_lookup(argv[5])) == NULLIF){
  207.         tprintf(Badinterface,argv[5]);
  208.         return 1;
  209.     }
  210.  
  211.     if(((protocol != TCP_PTCL) && (protocol != UDP_PTCL)) || (argc < 7)) {
  212.         lport = 0;
  213.         hport = 0;
  214.     } else {
  215.         if(strcmp(argv[6],"all") == 0){
  216.             lport = 0;
  217.         } else {
  218.             lport = atoi(argv[6]);
  219.         }
  220.         if((argc < 8) || (lport == 0))
  221.             hport = lport;
  222.         else
  223.             hport = atoi(argv[7]);
  224.     }
  225.  
  226.     if(strcmp(argv[1],"delete") == 0){
  227.         head = IPaccess;
  228.         for(tpacc = IPaccess;tpacc != NULLACCESS;head = tpacc,tpacc = tpacc->nxtiface){
  229.             if(tpacc->iface == ifp){
  230.                 for(btacc = tpacc;btacc != NULLACCESS;
  231.                      head = btacc,btacc = btacc->nxtbits){
  232.                     if((btacc->protocol == protocol) &&
  233.                        (btacc->source == source)     &&
  234.                        (btacc->sbits == sbits)       &&
  235.                        (btacc->target == target)     &&
  236.                        (btacc->tbits == tbits)       &&
  237.                        (btacc->lowport == lport)     &&
  238.                        (btacc->highport == hport)) { /*match*/
  239.                         bfacc = btacc; /* save to unalloc */
  240.                 /*now delete. watch for special cases*/
  241.                         if(btacc != tpacc){ /* not at head of list */
  242.                          head->nxtbits = btacc->nxtbits;
  243.                             free(bfacc);
  244.                             return 0;
  245.                         }
  246.                         if(btacc == IPaccess){ /* real special case */
  247.                         if(IPaccess->nxtbits == NULLACCESS)
  248.                             IPaccess = btacc->nxtiface;
  249.                         else {
  250.                             IPaccess = btacc->nxtbits;
  251.                             (btacc->nxtbits)->nxtiface = btacc->nxtiface;
  252.                         }
  253.                         } else { /* we know tpacc=btacc <> IPaccess */
  254.                         if(btacc->nxtbits == NULLACCESS)
  255.                             head->nxtiface = btacc->nxtiface;
  256.                         else {
  257.                             head->nxtiface = btacc->nxtbits;
  258.                             (btacc->nxtbits)->nxtiface = btacc->nxtiface;
  259.                         }
  260.                         }
  261.                     free(bfacc);
  262.                     return 0;
  263.                     }
  264.                 }
  265.             }
  266.         }
  267.         tprintf("Not found.\n");
  268.         return 1;
  269.     }
  270.     /* add the access */
  271.     addaccess(protocol,source,sbits,target,tbits,ifp,lport,hport,state);
  272.     return 0;
  273. }
  274. #endif
  275. static int
  276. doipaddr(argc,argv,p)
  277. int argc;
  278. char *argv[];
  279. void *p;
  280. {
  281.     int32 n;
  282.  
  283.     if(argc < 2) {
  284.         tprintf("%s\n",inet_ntoa(Ip_addr));
  285.     } else if((n = resolve(argv[1])) == 0){
  286.         tprintf(Badhost,argv[1]);
  287.         return 1;
  288.     } else
  289.         Ip_addr = n;
  290.     return 0;
  291. }
  292. static int
  293. dortimer(argc,argv,p)
  294. int argc;
  295. char *argv[];
  296. void *p;
  297. {
  298.     return setlong(&ipReasmTimeout,"IP reasm timeout (sec)",argc,argv);
  299. }
  300. static int
  301. dottl(argc,argv,p)
  302. int argc;
  303. char *argv[];
  304. void *p;
  305. {
  306.     return setlong(&ipDefaultTTL,"IP Time-to-live",argc,argv);
  307. }
  308.  
  309.  
  310. /* Display and/or manipulate routing table */
  311. int
  312. doroute(argc,argv,p)
  313. int argc;
  314. char *argv[];
  315. void *p;
  316. {
  317.     register int i,bits;
  318.     register struct route *rp;
  319.  
  320.     if(argc >= 2)
  321.         return subcmd(Rtcmds,argc,argv,p);
  322.  
  323.     /* Dump IP routing table
  324.      * Dest            Len Interface    Gateway          Use
  325.      * 192.001.002.003 32  sl0          192.002.003.004  0
  326.      */
  327.     Current->flowmode = 1;        /* start *more* processing */
  328.     tprintf(
  329. "Dest            Len Interface    Gateway          Metric  P Timer  Use\n");
  330.  
  331.     for(bits=31;bits>=0;bits--){
  332.         for(i=0;i<HASHMOD;i++){
  333.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  334.                 if(dumproute(rp) == EOF){
  335.                     Current->flowmode = 0;
  336.                     return 0;
  337.                 }
  338.             }
  339.         }
  340.     }
  341.     if(R_default.iface != NULLIF)
  342.         dumproute(&R_default);
  343.     Current->flowmode = 0;
  344.  
  345.     return 0;
  346. }
  347. /* Add an entry to the routing table
  348.  * E.g., "add 1.2.3.4 ax0 5.6.7.8 3"
  349.  */
  350. static int
  351. doadd(argc,argv,p)
  352. int argc;
  353. char *argv[];
  354. void *p;
  355. {
  356.     struct iface *ifp;
  357.     int32 dest,gateway;
  358.     unsigned bits;
  359.     char *bitp;
  360.     int32 metric;
  361.     char private;
  362.  
  363.     if(strncmp(argv[0],"addp",4) == 0)
  364.         private = 1;
  365.     else
  366.         private = 0;
  367.     if(strcmp(argv[1],"default") == 0){
  368.         dest = 0L;
  369.         bits = 0;
  370.     } else {
  371.         /* If IP address is followed by an optional slash and
  372.          * a length field, (e.g., 128.96/16) get it;
  373.          * otherwise assume a full 32-bit address
  374.          */
  375.         if((bitp = strchr(argv[1],'/')) != NULLCHAR){
  376.             /* Terminate address token for resolve() call */
  377.             *bitp++ = '\0';
  378.             bits = atoi(bitp);
  379.         } else
  380.             bits = 32;
  381.  
  382.         if((dest = resolve(argv[1])) == 0){
  383.             tprintf(Badhost,argv[1]);
  384.             return 1;
  385.         }
  386.     }
  387.     if((ifp = if_lookup(argv[2])) == NULLIF){
  388.         tprintf(Badinterface,argv[2]);
  389.         return 1;
  390.     }
  391.  
  392.     metric = 1;
  393.  
  394.     if(argc > 3){
  395.         /* Next "trick is needed to set the metric on subnets
  396.          * higher as the default 1 for rspf.
  397.          * route add subnet/bits iface default 10  
  398.          */
  399.         if(strcmp(argv[3],"direct") == 0){    /* N1BEE */
  400.              gateway = 0;
  401.         /* calculate a nice metric based on subnet mask size */
  402.             if(bits != 0 && bits < 32)
  403.                 metric = (39 - bits) * 5 / 17;
  404.         } else {
  405.             if((gateway = resolve(argv[3])) == 0){
  406.                 tprintf(Badhost,argv[3]);
  407.                 return 1;
  408.             }
  409.         }
  410.     } else {
  411.         gateway = 0;
  412.     }
  413.     if (argc > 4)
  414.         metric = atol(argv[4]);
  415.  
  416.     if(rt_add(dest,bits,gateway,ifp,metric,0,private) == NULLROUTE)
  417.         tprintf("Can't add route\n");
  418. #ifdef    RSPF
  419.     if(!private)
  420.         rspfrouteupcall(dest,bits,gateway);    /* Do an RSPF upcall */
  421. #endif    /* RSPF */
  422.     return 0;
  423. }
  424. /* Drop an entry from the routing table
  425.  * E.g., "drop 128.96/16
  426.  */
  427. static int
  428. dodrop(argc,argv,p)
  429. int argc;
  430. char *argv[];
  431. void *p;
  432. {
  433.     char *bitp;
  434.     unsigned bits;
  435.     int32 n;
  436.  
  437.     if(strcmp(argv[1],"default") == 0){
  438.         n = 0L;
  439.         bits = 0;
  440.     } else {
  441.         /* If IP address is followed by an optional slash and length field,
  442.          * (e.g., 128.96/16) get it; otherwise assume a full 32-bit address
  443.          */
  444.         if((bitp = strchr(argv[1],'/')) != NULLCHAR){
  445.             /* Terminate address token for resolve() call */
  446.             *bitp++ = '\0';
  447.             bits = atoi(bitp);
  448.         } else
  449.             bits = 32;
  450.  
  451.         if((n = resolve(argv[1])) == 0){
  452.             tprintf(Badhost,argv[1]);
  453.             return 1;
  454.         }
  455.     }
  456.     return rt_drop(n,bits);
  457. }
  458. /* Force a timeout on all temporary routes */
  459. static int
  460. doflush(argc,argv,p)
  461. int argc;
  462. char *argv[];
  463. void *p;
  464. {
  465.     register struct route *rp;
  466.     struct route *rptmp;
  467.     int i,j;
  468.     
  469.     if(R_default.timer.state == TIMER_RUN){
  470.         rt_drop(0,0);    /* Drop default route */
  471.     }
  472.     for(i=0;i<HASHMOD;i++){
  473.         for(j=0;j<32;j++){
  474.             for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  475.                 rptmp = rp->next;
  476.                 if(rp->timer.state == TIMER_RUN){
  477.                     rt_drop(rp->target,rp->bits);
  478.                 }
  479.             }
  480.         }
  481.     }
  482.     return 0;
  483. }
  484. /* Dump a routing table entry */
  485. static int
  486. dumproute(rp)
  487. register struct route *rp;
  488. {
  489.     char *cp;
  490.  
  491.     if(rp->target != 0)
  492.         cp = inet_ntoa(rp->target);
  493.     else
  494.         cp = "default";
  495.     tprintf("%-16s",cp);
  496.     tprintf("%-4u",rp->bits);
  497.     tprintf("%-13s",rp->iface->name);
  498.     if(rp->gateway != 0)
  499.         cp = inet_ntoa(rp->gateway);
  500.     else
  501.         cp = "";
  502.     tprintf("%-17s",cp);
  503.     tprintf("%-8lu",rp->metric);
  504.     tprintf("%c ",(rp->flags & RTPRIVATE) ? 'P' : ' ');
  505.     if(rp->timer.state == TIMER_STOP){
  506.         if(rp->timer.duration == 2)tprintf("rspf   ");
  507.         else tprintf("man    ");
  508.     } else tprintf("%-7lu",read_timer(&rp->timer) / 1000L);
  509.     return tprintf("%lu\n",rp->uses);
  510. }
  511.  
  512. static int
  513. dolook(argc,argv,p)
  514. int argc;
  515. char *argv[];
  516. void *p;
  517. {
  518.     struct route *rp;
  519.     int32 addr;
  520.  
  521.     addr = resolve(argv[1]);
  522.     if(addr == 0){
  523.         tprintf(Badhost,argv[1]);
  524.         return 1;
  525.     }
  526.     if((rp = rt_lookup(addr)) == NULLROUTE){
  527.         tprintf("Host %s (%s) unreachable\n",argv[1],inet_ntoa(addr));
  528.         return 1;
  529.     }
  530.     dumproute(rp);
  531.     return 0;
  532. }
  533.  
  534. static int
  535. doipstat(argc,argv,p)
  536. int argc;
  537. char *argv[];
  538. void *p;
  539. {
  540.     register struct reasm *rp;
  541.     register struct frag *fp;
  542.     int i;
  543.  
  544.     for(i=1;i<=NUMIPMIB;i++){
  545.         tprintf("(%2u)%-20s%10lu",i,
  546.          Ip_mib[i].name,Ip_mib[i].value.integer);
  547.         if(i % 2)
  548.             tprintf("     ");
  549.         else
  550.             tprintf("\n");
  551.     }
  552.     if((i % 2) == 0)
  553.         tprintf("\n");
  554.  
  555.     if(Reasmq != NULLREASM)
  556.         tprintf("Reassembly fragments:\n");
  557.     for(rp = Reasmq;rp != NULLREASM;rp = rp->next){
  558.         tprintf("src %s",inet_ntoa(rp->source));
  559.         tprintf(" dest %s",inet_ntoa(rp->dest));
  560.         if(tprintf(" id %u pctl %u time %lu len %u\n",
  561.          rp->id,uchar(rp->protocol),read_timer(&rp->timer),
  562.          rp->length) == EOF)
  563.             break;
  564.         for(fp = rp->fraglist;fp != NULLFRAG;fp = fp->next){
  565.             if(tprintf(" offset %u last %u\n",fp->offset,
  566.             fp->last) == EOF)
  567.                 break;
  568.         }
  569.     }
  570.     return 0;
  571. }
  572.